﻿Imports System
Imports System.CodeDom
Imports System.CodeDom.Compiler
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.ComponentModel.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Globalization
Imports System.IO
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Serialization
Imports System.Xml

Namespace System.Workflow.ComponentModel.Compiler
    Friend NotInheritable Class WorkflowCompilerInternal
        Inherits MarshalByRefObject
        ' Methods
        Public Function Compile(ByVal parameters As WorkflowCompilerParameters, ByVal allFiles As String()) As WorkflowCompilerResults
            Dim results As New WorkflowCompilerResults(parameters.TempFiles)
            Dim strings As New StringCollection
            Dim strings2 As New StringCollection
            Dim str As String
            For Each str In allFiles
                If str.EndsWith(".xoml", StringComparison.OrdinalIgnoreCase) Then
                    strings.Add(str)
                Else
                    strings2.Add(str)
                End If
            Next
            Dim array As String() = New String(strings.Count  - 1) {}
            strings.CopyTo(array, 0)
            Dim strArray2 As String() = New String(strings2.Count  - 1) {}
            strings2.CopyTo(strArray2, 0)
            XomlCompilerHelper.FixReferencedAssemblies(parameters, results, parameters.LibraryPaths)
            Dim resolver As New ReferencedAssemblyResolver(parameters.ServiceProvider, parameters.ReferencedAssemblies, parameters.LocalAssembly)
            AddHandler AppDomain.CurrentDomain.AssemblyResolve, New ResolveEventHandler(AddressOf resolver.ResolveEventHandler)
            Dim container As ServiceContainer = If((Not parameters.ServiceProvider Is Nothing), New ServiceContainer(parameters.ServiceProvider), New ServiceContainer)
            If (container.GetService(GetType(IWorkflowCompilerOptionsService)) Is Nothing) Then
                container.AddService(GetType(IWorkflowCompilerOptionsService), New WorkflowCompilerOptionsService(parameters))
            End If
            If (container.GetService(GetType(ITypeProvider)) Is Nothing) Then
                Dim serviceInstance As New TypeProvider(If((Not parameters.ServiceProvider Is Nothing), parameters.ServiceProvider, New ServiceContainer))
                Dim flag As Boolean = False
                Dim location As String = GetType(String).Assembly.Location
                Dim str3 As String
                For Each str3 In parameters.ReferencedAssemblies
                    If (Not flag AndAlso str3.Equals(location, StringComparison.OrdinalIgnoreCase)) Then
                        flag = True
                    End If
                    serviceInstance.AddAssemblyReference(str3)
                Next
                If Not flag Then
                    serviceInstance.AddAssemblyReference(location)
                End If
                container.AddService(GetType(ITypeProvider), serviceInstance)
            End If
            parameters.ServiceProvider = container
            Dim files As TempFileCollection = Nothing
            Dim localAssemblyPath As String = String.Empty
            Try 
                parameters.LocalAssembly = Me.GenerateLocalAssembly(array, strArray2, parameters, results, files, localAssemblyPath)
                If (Not parameters.LocalAssembly Is Nothing) Then
                    resolver.SetLocalAssembly(parameters.LocalAssembly)
                    Dim service As ITypeProvider = DirectCast(container.GetService(GetType(ITypeProvider)), ITypeProvider)
                    DirectCast(service, TypeProvider).SetLocalAssembly(parameters.LocalAssembly)
                    DirectCast(service, TypeProvider).AddAssembly(parameters.LocalAssembly)
                    results.Errors.Clear
                    XomlCompilerHelper.InternalCompileFromDomBatch(array, strArray2, parameters, results, localAssemblyPath)
                End If
            Catch exception As Exception
                Dim num2 As Integer = &H15C
                results.Errors.Add(New WorkflowCompilerError(String.Empty, -1, -1, num2.ToString(CultureInfo.InvariantCulture), SR.GetString("Error_CompilationFailed", New Object() { exception.Message })))
            Finally
                If ((Not files Is Nothing) AndAlso Not parameters.TempFiles.KeepFiles) Then
                    Dim directoryName As String = String.Empty
                    If File.Exists(localAssemblyPath) Then
                        directoryName = Path.GetDirectoryName(localAssemblyPath)
                    End If
                    Dim str6 As String
                    For Each str6 In files
                        Try 
                            File.Delete(str6)
                            [Continue] For
                        Catch obj1 As Object
                            [Continue] For
                        End Try
                    Next
                    Try 
                        If Not String.IsNullOrEmpty(directoryName) Then
                            Directory.Delete(directoryName)
                        End If
                    Catch obj2 As Object
                    End Try
                End If
            End Try
            Return results
        End Function

        Friend Shared Function GenerateCodeFromFileBatch(ByVal files As String(), ByVal parameters As WorkflowCompilerParameters, ByVal results As WorkflowCompilerResults) As CodeCompileUnit
            Dim service As IWorkflowCompilerOptionsService = [TryCast](parameters.ServiceProvider.GetService(GetType(IWorkflowCompilerOptionsService)),IWorkflowCompilerOptionsService)
            If (service Is Nothing) Then
                Throw New Exception(SR.GetString("General_MissingService", New Object() { GetType(IWorkflowCompilerOptionsService).FullName }))
            End If
            Dim unit As New CodeCompileUnit
            Dim str As String
            For Each str In files
                Dim rootActivity As Activity = Nothing
                Try 
                    Dim manager As New DesignerSerializationManager(parameters.ServiceProvider)
                    [Using] manager.CreateSession
                        Dim xomlSerializationManager As New WorkflowMarkupSerializationManager(manager)
                        xomlSerializationManager.WorkflowMarkupStack.Push(parameters)
                        xomlSerializationManager.LocalAssembly = parameters.LocalAssembly
                        [Using] reader As XmlReader = XmlReader.Create(str)
                            rootActivity = WorkflowMarkupSerializationHelpers.LoadXomlDocument(xomlSerializationManager, reader, str)
                        End [Using]
                        If (Not parameters.LocalAssembly Is Nothing) Then
                            Dim obj2 As Object
                            For Each obj2 In manager.Errors
                                If TypeOf obj2 Is WorkflowMarkupSerializationException Then
                                    results.Errors.Add(New WorkflowCompilerError(str, DirectCast(obj2, WorkflowMarkupSerializationException)))
                                Else
                                    Dim num2 As Integer = &H15B
                                    results.Errors.Add(New WorkflowCompilerError(str, -1, -1, num2.ToString(CultureInfo.InvariantCulture), obj2.ToString))
                                End If
                            Next
                        End If
                    End [Using]
                Catch exception As WorkflowMarkupSerializationException
                    results.Errors.Add(New WorkflowCompilerError(str, exception))
                    goto Label_0334
                Catch exception2 As Exception
                    Dim num3 As Integer = &H15B
                    results.Errors.Add(New WorkflowCompilerError(str, -1, -1, num3.ToString(CultureInfo.InvariantCulture), SR.GetString("Error_CompilationFailed", New Object() { exception2.Message })))
                    goto Label_0334
                End Try
                If (rootActivity Is Nothing) Then
                    Dim num4 As Integer = &H15B
                    results.Errors.Add(New WorkflowCompilerError(str, 1, 1, num4.ToString(CultureInfo.InvariantCulture), SR.GetString("Error_RootActivityTypeInvalid")))
                ElseIf String.IsNullOrEmpty([TryCast](rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty),String)) Then
                    Dim num5 As Integer = &H15B
                    results.Errors.Add(New WorkflowCompilerError(str, 1, 1, num5.ToString(CultureInfo.InvariantCulture), SR.GetString("Error_CannotCompile_No_XClass")))
                Else
                    If (parameters.CompileWithNoCode AndAlso XomlCompilerHelper.HasCodeWithin(rootActivity)) Then
                        Dim error As New ValidationError(SR.GetString("Error_CodeWithinNotAllowed"), &H16A)
                        [error].UserData.Item(GetType(Activity)) = rootActivity
                        results.Errors.Add(XomlCompilerHelper.CreateXomlCompilerError([error], parameters))
                    End If
                    Dim errors As New ValidationErrorCollection
                    Dim error2 As ValidationError
                    For Each error2 In WorkflowCompilerInternal.ValidateIdentifiers(parameters.ServiceProvider, rootActivity)
                        results.Errors.Add(XomlCompilerHelper.CreateXomlCompilerError(error2, parameters))
                    Next
                    If Not results.Errors.HasErrors Then
                        unit.Namespaces.AddRange(WorkflowMarkupSerializationHelpers.GenerateCodeFromXomlDocument(rootActivity, str, service.RootNamespace, CompilerHelpers.GetSupportedLanguage(parameters.ServiceProvider), parameters.ServiceProvider))
                    End If
                End If
            Label_0334:
            Next
            WorkflowMarkupSerializationHelpers.FixStandardNamespacesAndRootNamespace(unit.Namespaces, service.RootNamespace, CompilerHelpers.GetSupportedLanguage(parameters.ServiceProvider))
            Return unit
        End Function

        Private Function GenerateLocalAssembly(ByVal files As String(), ByVal codeFiles As String(), ByVal parameters As WorkflowCompilerParameters, ByVal results As WorkflowCompilerResults, <Out> ByRef tempFiles2 As TempFileCollection, <Out> ByRef localAssemblyPath As String) As Assembly
            localAssemblyPath = String.Empty
            tempFiles2 = Nothing
            Dim unit As CodeCompileUnit = WorkflowCompilerInternal.GenerateCodeFromFileBatch(files, parameters, results)
            If results.Errors.HasErrors Then
                Return Nothing
            End If
            Dim supportedLanguage As SupportedLanguages = CompilerHelpers.GetSupportedLanguage(parameters.LanguageToUse)
            Dim codeDomProvider As CodeDomProvider = CompilerHelpers.GetCodeDomProvider(supportedLanguage)
            Dim parameters2 As CompilerParameters = XomlCompilerHelper.CloneCompilerParameters(parameters)
            parameters2.TempFiles.KeepFiles = True
            tempFiles2 = parameters2.TempFiles
            parameters2.GenerateInMemory = True
            If String.IsNullOrEmpty(parameters.OutputAssembly) Then
                localAssemblyPath = parameters2.OutputAssembly = parameters2.TempFiles.AddExtension("dll")
                goto Label_00F8
            End If
            Dim basePath As String = parameters2.TempFiles.BasePath
            Dim num As Integer = 0
        Label_0099:
            Try 
                Directory.CreateDirectory(basePath)
            Catch obj1 As Object
                basePath = (parameters2.TempFiles.BasePath & num++)
                goto Label_0099
            End Try
            localAssemblyPath = parameters2.OutputAssembly = (basePath & "\" & Path.GetFileName(parameters2.OutputAssembly))
            parameters2.TempFiles.AddFile(localAssemblyPath, True)
        Label_00F8:
            parameters2.TreatWarningsAsErrors = False
            If ((Not parameters2.CompilerOptions Is Nothing) AndAlso (parameters2.CompilerOptions.Length > 0)) Then
                Dim compilerOptions As String = parameters2.CompilerOptions
                Dim list As New ArrayList
                Dim startIndex As Integer = 0
                Dim num3 As Integer = 0
                Dim flag As Boolean = False
                Do While (num3 < compilerOptions.Length)
                    If (compilerOptions.Chars(num3) = """"c) Then
                        flag = Not flag
                    ElseIf ((compilerOptions.Chars(num3) = " "c) AndAlso Not flag) Then
                        If (startIndex = num3) Then
                            startIndex += 1
                        Else
                            Dim str3 As String = compilerOptions.Substring(startIndex, (num3 - startIndex))
                            list.Add(str3)
                            startIndex = (num3 + 1)
                        End If
                    End If
                    num3 += 1
                Loop
                If (startIndex <> num3) Then
                    Dim str4 As String = compilerOptions.Substring(startIndex, (num3 - startIndex))
                    list.Add(str4)
                End If
                Dim strArray As String() = [TryCast](list.ToArray(GetType(String)),String())
                parameters2.CompilerOptions = String.Empty
                Dim str5 As String
                For Each str5 In strArray
                    If (((str5.Length > 0) AndAlso Not str5.StartsWith("/delaysign", StringComparison.OrdinalIgnoreCase)) AndAlso (Not str5.StartsWith("/keyfile", StringComparison.OrdinalIgnoreCase) AndAlso Not str5.StartsWith("/keycontainer", StringComparison.OrdinalIgnoreCase))) Then
                        parameters2.CompilerOptions = (parameters2.CompilerOptions & " " & str5)
                    End If
                Next
            End If
            parameters2.CompilerOptions = If((parameters2.CompilerOptions Is Nothing), "/optimize-", (parameters2.CompilerOptions & " /optimize-"))
            parameters2.IncludeDebugInformation = True
            If (supportedLanguage = SupportedLanguages.CSharp) Then
                parameters2.CompilerOptions = (parameters2.CompilerOptions & " /unsafe")
            End If
            Dim list2 As New ArrayList(DirectCast(parameters.UserCodeCompileUnits, ICollection))
            list2.Add(unit)
            Dim list3 As New ArrayList
            list3.AddRange(codeFiles)
            list3.AddRange(XomlCompilerHelper.GenerateFiles(codeDomProvider, parameters2, DirectCast(list2.ToArray(GetType(CodeCompileUnit)), CodeCompileUnit())))
            Dim results2 As CompilerResults = codeDomProvider.CompileAssemblyFromFile(parameters2, DirectCast(list3.ToArray(GetType(String)), String()))
            If results2.Errors.HasErrors Then
                results.AddCompilerErrorsFromCompilerResults(results2)
                Return Nothing
            End If
            If Not TypeOf parameters.ServiceProvider.GetService(GetType(IWorkflowCompilerOptionsService)) Is IWorkflowCompilerOptionsService Then
                Throw New Exception(SR.GetString("General_MissingService", New Object() { GetType(IWorkflowCompilerOptionsService).FullName }))
            End If
            Return results2.CompiledAssembly
        End Function

        Public Overrides Function InitializeLifetimeService() As Object
            Return Nothing
        End Function

        Private Shared Function ValidateIdentifiers(ByVal serviceProvider As IServiceProvider, ByVal activity As Activity) As ValidationErrorCollection
            Dim validationErrors As New ValidationErrorCollection
            Dim names As New Dictionary([Of] String, Integer)
            Dim walker As New Walker
            AddHandler walker.FoundActivity, Function (ByVal walker2 As Walker, ByVal e As WalkerEventArgs) 
                Dim currentActivity As Activity = e.CurrentActivity
                If Not currentActivity.Enabled Then
                    e.Action = WalkerAction.Skip
                Else
                    Dim item As ValidationError = Nothing
                    If names.ContainsKey(currentActivity.QualifiedName) Then
                        If (Not names.Item(currentActivity.QualifiedName) Is 1) Then
                            item = New ValidationError(SR.GetString("Error_DuplicatedActivityID", New Object() { currentActivity.QualifiedName }), &H602, False, "Name")
                            item.UserData.Item(GetType(Activity)) = currentActivity
                            validationErrors.Add(item)
                            names.Item(currentActivity.QualifiedName) = 1
                        End If
                    ElseIf Not String.IsNullOrEmpty(currentActivity.Name) Then
                        names.Item(currentActivity.Name) = 0
                        item = ValidationHelpers.ValidateIdentifier("Name", serviceProvider, currentActivity.Name)
                        If (Not item Is Nothing) Then
                            item.UserData.Item(GetType(Activity)) = currentActivity
                            validationErrors.Add(item)
                        End If
                    End If
                End If
            End Function
            walker.Walk(activity)
            Return validationErrors
        End Function

    End Class
End Namespace

